<?php

\public\index.php
  require __DIR__.'/../bootstrap/autoload.php';

\bootstrap\autoload.php
  require __DIR__.'/../vendor/autoload.php';

\vendor\autoload.php
  require_once __DIR__ . '/composer/autoload_real.php';
  return ComposerAutoloaderInitbac45f0e43675e23e3d7e7ad61d6280e::getLoader();
  // 其实这个return 没什么用，从上面的流程看到，并没有变量来接收返回值。

\vendor\composer\autoload_real.php
  有一个类，就是上面的 ComposerAutoloaderInitbac45f0e43675e23e3d7e7ad61d6280e；
  还有一个方法，就是 composerRequirebac45f0e43675e23e3d7e7ad61d6280e，用于引入文件并保证不会重复引入。
  那么关键的就是这个类了。执行类的静态方法 getLoader。
  1、定义一个临时的类加载机制，通过
    self::$loader = $loader = new \Composer\Autoload\ClassLoader();
    加载了 \vendor\composer\ClassLoader.php 类，实例化，赋值给静态属性，然后删除了这个临时类加载机制。
    也就是说，这个类加载机制仅仅用了一次，就是加载 \vendor\composer\ClassLoader.php。
  2、根据条件，引入了 \vendor\composer\autoload_static.php。
    这个文件，是使用 composer 下载包时动态创建、修改的，也就是添加包、删除包等操作时会动态处理文件的内容。
    以 laravel 框架为例。
    GitHub 上框架的名称是 laravel/framework，仓库的目录下正有一个 composer.json 文件。
    composer下载后，放在 vendor下，之后的目录结构就是包在 GitHub 上的名称构成的子路径，也就是 laravel/framework。
    然后把该仓库下的文件、目录等放在 laravel/framework 目录下。
    这正是我们比较 GitHub 和项目 vendor 下的结构得到的结论。
    composer 下载完毕，分析 composer.json 的内容，把需要的信息放入到 \vendor\composer\autoload_static.php。
    主要的信息主要是：
    "name": "laravel/framework",
    "autoload": {
        "files": [
            "src/Illuminate/Foundation/helpers.php",
            "src/Illuminate/Support/helpers.php"
        ],
        "psr-4": {
            "Illuminate\\": "src/Illuminate/"
        }
    },
    说明：
      本包的php 文件有两种加载方式：
        两个helpers.php 属于硬加载，也就是直接加载，而不是在需要时才加载。
          这两个文件出现在了 autoload_static.php 中的 public static $files 的数组中：
          'f0906e6318348a765ffb6eb24e0d0938' => __DIR__ . '/..' . '/laravel/framework/src/Illuminate/Foundation/helpers.php',
          '58571171fd5812e6e447dce228f52f4d' => __DIR__ . '/..' . '/laravel/framework/src/Illuminate/Support/helpers.php',
          可以看到具体的值是：name 的值 + autoload.files 的每一个具体值。
        其他的编程接口都是属于软加载，也就是需要时加载，并且是以 PSR-4 的标准来加载的。
          分步走：
          1、命名空间 Illuminate，首字母是 I，出现在 autoload_static.php 中的 public static $prefixLengthsPsr4 数组中：
            'I' =>
            array (
                'Illuminate\\' => 11,
            ),
          2、命名空间本身被处理到了 autoload_static.php 中的 public static $prefixDirsPsr4 数组中：
            'Illuminate\\' =>
            array (
                0 => __DIR__ . '/..' . '/laravel/framework/src/Illuminate',
            ),
            可以看到值就是 name 的值 + 命名空间对应的值。
  3、给上面得到的实例添加属性。
    具体做法就是通过
    call_user_func(\Composer\Autoload\ComposerStaticInitbac45f0e43675e23e3d7e7ad61d6280e::getInitializer($loader));
    实现把 autoload_static.php 的几个静态属性，添加到 $loader 上。
  4、又注册了类的加载机制：$loader->register(true); register 方法就是：
    public function register($prepend = false)
    {
        spl_autoload_register(array($this, 'loadClass'), true, $prepend);
    }
    而自己的 loadClass 方法则是：
    public function loadClass($class)
    {
        if ($file = $this->findFile($class)) {
            includeFile($file);

            return true;
        }
    }
  5、硬加载 $loader 的 $files 里的那些 .php 文件。

此时，需要硬加载的 .php 文件以及加载了，也注册了类的加载机制。

再回到 \public\index.php 内接着执行：
  $app = require_once __DIR__.'/../bootstrap/app.php';

\bootstrap\app.php
  $app = new Illuminate\Foundation\Application(
      realpath(__DIR__.'/../')
  );
  此时就使用到了上面注册了的类的加载机制。
  具体加载过程：
  loadClass('Illuminate\Foundation\Application');
  findFile('Illuminate\Foundation\Application');
  findFileWithExtension('Illuminate\Foundation\Application', '.php');
  在这个方法内，根据 composer 规定的类加载先后顺序查找文件：
  // PSR-4 lookup
  // PSR-4 fallback dirs
  // PSR-0 lookup
  // PSR-0 fallback dirs
  // PSR-0 include paths.
  当然，laravel 框架的 composer.json 中已经指明了使用 psr-4 标准来加载。
  找到首字母 I，在 $prefixLengthsPsr4 找到了。
  按 \ 分隔，依照最大精确度来匹配。由于最后一个是类名，所以从最后一个 \的前面部分找，找之前会在末尾加上 \\，
  也就是按 Illuminate\Foundation\\ 在 $prefixDirsPsr4 的数组中找，没找到。
  以上一次的 Illuminate\Foundation 为基准，再以其中最后一个 \的前面部分找，也就是 Illuminate\\ 找，找到了：
  array (
      0 => __DIR__ . '/..' . '/laravel/framework/src/Illuminate',
  ),
  遍历这个找到的key 的值。
  以数组的每个元素的值，加上指定 \ 位置后面的部分 Foundation\Application，再加上 .php，就是：
  __DIR__ . '/..' . '/laravel/framework/src/Illuminate/Foundation/Application.php'。
  找到了，于是通过 loadClass 方法中的 includeFile 函数内的 include 指令引入该类文件。

  实例化成功，得到 $app。

  得到 $app 后，立即绑定了三个实现，分别是 http 请求处理、控制台操作处理以及调试异常处理。

\public\index.php
  使用 $app 来接收 \bootstrap\app.php 返回的 $app。
  通过 $kernel = $app->make(Illuminate\Contracts\Http\Kernel::class);
  创建了基于 http 的内核。
  之后调用封装的请求处理、响应处理来结束请求响应流：
  $response = $kernel->handle(
    $request = Illuminate\Http\Request::capture()
  );
  $response->send();
  $kernel->terminate($request, $response);
